package com.baiye.www.serializer;

import com.google.gson.*;
import com.google.gson.GsonBuilder;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;

/**
 * @author GUOZHIPENG
 * @version 1.0
 * @date 2021/12/2 9:03
 */
@Slf4j
public enum SerializeType implements Serializer {
    /**
     * JDK原生序列化
     */
    Java{
        @Override
        public <T> T deserialize(Class<T> clazz, byte[] bytes) {
            try {
                ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
                return (T) ois.readObject();
            } catch (IOException | ClassNotFoundException e) {
                log.error("Failed to serialize deserialize java");
                e.printStackTrace();
            }
            return null;
        }

        @Override
        public <T> byte[] serialize(T object) {

            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(object);
                return bos.toByteArray();
            } catch (IOException e) {
                log.error("Failed to serialize serialize java");
                e.printStackTrace();
            }
            return null;
        }
    },
    /**
     * Json序列化
     */
    Json{
        @Override
        public <T> T deserialize(Class<T> clazz, byte[] bytes) {
            Gson gson = new GsonBuilder().registerTypeAdapter(Class.class, new SerializeType.ClassCodec()).create();
            //Gson gson=new Gson();
            String json = new String(bytes, StandardCharsets.UTF_8);
            log.debug("deserialize--{}",json);
            System.out.println("json--deserialize--"+json);
            return gson.fromJson(json, clazz);
        }

        @Override
        public <T> byte[] serialize(T object) {
            //Gson gson = new GsonBuilder().registerTypeAdapter(Class.class, new SerializeType.ClassCodec()).create();
            Gson gson=new Gson();
            String json = null;
            try {
                json = gson.toJson(object);
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.debug("serialize--{}",json);
            System.out.println("json--serialize--"+json);
            return json.getBytes(StandardCharsets.UTF_8);
        }
    },
    /**
     * google Protobuf 序列化
     */
    Protobuf{
        @Override
        public <T> T deserialize(Class<T> clazz, byte[] bytes) {
            return null;
        }

        @Override
        public <T> byte[] serialize(T object) {
            return new byte[0];
        }
    };


    /**
     * 自定义类型转换器，解决 Gson String序列化
     */
    class ClassCodec implements JsonSerializer<Class<?>>, JsonDeserializer<Class<?>> {

        @Override
        public Class<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            try {
                String str = json.getAsString();
                return Class.forName(str);
            } catch (ClassNotFoundException e) {
                throw new JsonParseException(e);
            }
        }

        @Override             //   String.class
        public JsonElement serialize(Class<?> src, Type typeOfSrc, JsonSerializationContext context) {
            // class -> json
            return new JsonPrimitive(src.getName());
        }
    }

}
